#pragma once 
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <string>
#include <vector>
#include <iostream>
#include <unordered_map>

#include "ConnetInfo.hpp"

using namespace std;
//个人的信息
class UserInfo
{
    public:
        UserInfo(string nick_name,string school,string passwd,uint32_t user_id)
        {
            nick_name_ = nick_name;
            school_ = school;
            passwd_ = passwd;
            user_id_ = user_id;
            //status_ = Login_Success;
            memset((void*)&addr_,'\0',sizeof(addr_));
            addr_len_ = -1;
        }

        void SetAddr(struct sockaddr_in addr)
        {
            memcpy(&addr_,&addr,sizeof(addr));
        }

        void SetAddrlen(socklen_t len)
        {
            addr_len_ = len;
        }

        struct sockaddr_in* GetAddr()
        {
            return &addr_;
        }

        socklen_t GetAddrLen()
        {
            return addr_len_;
        }
        string& Getpasswd()
        {
            return passwd_;
        }

        void SetStatus(int status)
        {   
            status_ =  status;
        }
        //获得状态
        int GetStatus()
        {
            return status_;
        }
    private:
        string nick_name_;
        string school_;
        string passwd_;
        uint32_t user_id_;
        int status_;
        //对端udp地址信息
        struct sockaddr_in addr_;
        socklen_t addr_len_;
};

class UserManager
{
    public:
        UserManager()
        {
            prepared_id_ = 0;
            pthread_mutex_init(&mutex_,NULL);
            map_.clear();
            Online_user_.clear();
        }
        ~UserManager()
        {
            pthread_mutex_destroy(&mutex_);
        }
        int  DealRegister(const string& nick_name,const string& school,const string& passwd,uint32_t* id)
        {
           //判断字段是否为空
           if(nick_name.empty() || school.empty() || passwd.empty())
           {
               return -1;
           }
           UserInfo ui(nick_name,school,passwd,prepared_id_);   
           pthread_mutex_lock(&mutex_);
           map_.insert(make_pair(prepared_id_,ui));
           *id = prepared_id_;
           prepared_id_++;
           pthread_mutex_unlock(&mutex_);
           return 0;
        }
        int DealLogin(const uint32_t& id,const string& passwd)
        {
            //判断字段是否为空
            if(passwd.size() == 0)
            {
                return -1;
            }
            //在map_中寻找匹配的id
            unordered_map<uint32_t,UserInfo>::iterator iter;
            pthread_mutex_lock(&mutex_);
            iter = map_.find(id);
            //说明没有找到
            if(iter == map_.end())
            {
                pthread_mutex_unlock(&mutex_);
                return -1;
            }
            //找到id 匹配密码正不正确
             string ret = iter->second.Getpasswd();
             if(ret != passwd)
             {
                pthread_mutex_unlock(&mutex_);
                return -1;
             }
             //成功登录
             iter->second.SetStatus(Login_Success);
             pthread_mutex_unlock(&mutex_);
             return 0;
        }
        bool IsLogin(uint32_t user_id,struct sockaddr_in addr,socklen_t len)
        {
            //利用user_id看是否是在线状态
            unordered_map<uint32_t,UserInfo>::iterator iter;
            pthread_mutex_lock(&mutex_);
            iter = map_.find(user_id);
            if(iter == map_.end())
            {
                return false;
            }
            //找到了
            //第一次登录上来，没记录过它的地址信息
            if(iter->second.GetStatus() != Login_Online)
            {
                iter->second.SetStatus(Login_Online);
                iter->second.SetAddr(addr);//设置udp地址
                iter->second.SetAddrlen(len);//设置地址的长度
                //插入在线列表当中
                Online_user_.push_back(iter->second);
            }
            //第N次登录
            pthread_mutex_unlock(&mutex_);
            return true;
            
        }
        //获得在线用户列表
    public:
        vector<UserInfo> GetOnlineUser()
        {
           return Online_user_;
        }
    private:
        //key:value
        unordered_map<uint32_t,UserInfo> map_;
        //预分配的id
        uint32_t prepared_id_;
        //互斥锁---预分配的id和关联容器线程不安全
        pthread_mutex_t mutex_;
        //在线用户列表
        vector<UserInfo> Online_user_;
};
